1 ESBOÇO FLUXO DE TRABALHO DO PRODUTO 2 - CÓDIGOS

1.1 PARTE I – Cuidados antes de começar a rodar os códigos no R

Pensar quais orientações são mais gerais e quais são importantes de acompanhar cada código.

1.1.1 Rstudio/Pacotes/versões/sistemas operacionais

Sobre os pacotes, seria bom ter uma listinha de ‘library’ no início de cada código? Talvez com uma breve explicação do que cada pacote faz, versão mínima… não sei.

OBS: essa tabela é uma referência para obtermos as versões dos pacotes ao final do desenvolvimento do script. Ela está automatizada, então quando terminarmos ele precisamos refaze-lo de forma que não gere mais mudança nas versões (tem que fazer a tabela na mão mesmo…).

# carregar pacote para formatar tabela
library(flextable)

# gerar informações sobre os pacotes carregados
info <- sessionInfo()

# gerar tabela com os pacotes e versões
tibble::tribble(
  ~Pacotes,                         ~Versão,
  version$language,                 version$version.string,
  info$otherPkgs$dplyr$Package,     info$otherPkgs$dplyr$Version,
  info$otherPkgs$Distance$Package,  info$otherPkgs$Distance$Version,
  info$otherPkgs$DT$Package,        info$otherPkgs$DT$Version,
  info$otherPkgs$flextable$Package, info$otherPkgs$flextable$Version,
  info$otherPkgs$plotly$Package,    info$otherPkgs$plotly$Version,
  info$otherPkgs$readr$Package,     info$otherPkgs$readr$Version,
  info$otherPkgs$tibble$Package,    info$otherPkgs$tibble$Version,
  info$otherPkgs$tidyr$Package,     info$otherPkgs$tidyr$Version,
) |> 
  qflextable() |> 
  set_caption(
    "Tabela xx = configuração de pacotes necessários e respectivas versões mínimas que devem ser utilizadas para reproduzir os códigos"
  )
Tabela xx = configuração de pacotes necessários e respectivas versões mínimas que devem ser utilizadas para reproduzir os códigos

Pacotes

Versão

R

R version 4.2.3 (2023-03-15)

dplyr

1.1.1

Distance

1.0.7

DT

0.27

flextable

0.9.1

plotly

4.10.1

readr

2.1.4

tibble

3.2.1

tidyr

1.3.0

NA
NA

1.1.2 Cuidados com a planilha .xlsx que será importada (para que mantenha o padrão da planilha de referência do ICMBio)

Algumas funções foram escritas para funcionar tomando como base de dados de referência a planilha em formato excel Planilha Oficial consolidada de Masto-aves 2014-21 Validada CEMAVE CPB CENAP.xlsx disponibilizada pelo Projeto Monitora. Estas funções carregam os dados e fazem uma série de transformações para devolve-los no formato padronizado do programa DISTANCE para Windows. Portanto, para garantir a reprodutibilidade dos códigos produzidos em versões atualizadas da base de dados do Monitora, é importante tomar alguns cuidados.

O primeiro e mais importante cuidado é manter os mesmos nomes das colunas em versões atualizadas da base de dados do Monitora. As primeiras funções, além de carregar os dados, aplicam uma série de transformações. Os nomes das colunas são alterados, e a essas são atribuídos tipos (data, caracter, fator , inteiro e numérico), linhas são eliminadas e novas colunas são gereadas. Para exemplificar, veja o código abaixo. Ele foi escrito para executar as primeiras transformações nos dados e constitui o corpo da função carregar_dados_filtrados().

O trecho do código que vai da linha 101 a 113 serve selecionar apenas as colunas de interesse presente nos dados originais. Note que os nomes das planilhas originais constam nesse trecho. Caso o nome de qualque uma dessas colunas seja alterado a função deixará de funcionar.

Outro aspecto importante é a presença de observações não preenchidas (ex. células vazias) nos dados originais. A função foi desenha para resolver alguns problemas presentes nos dados originais. Por exemplo, nas o trecho do código das linhas xx a xx as observações vazias (NAs) são substituidas pelo valor correto na coluna day_effort. Essa correção continnuará sendo realizada em versões atualizadas dos dados do Monitora. Porém, se outras colunas além das que estão sendo corrigidas possuirem observações vazias os dados serão carregados e transformados, porém outras funções podem ter o seu funcionamento comprometido. Por exemplo… (funções de visualização e do pacote distance que podem naõ funcionar devido a ausência de observação)

Outros cuidados…

Imaginando que a planilha de dados do monitora é algo dinâmico, que o nome das colunas pode ser editado…

1.1.3 Como abrir os arquivos: como salvar e descompactar a pasta. Abrir projeto

Um passo a passo de como salvar arquivo com os códigos e abrir.. Por exemplo, da forma como está é interessante descompactar a pasta e acessar os arquivos abrindo o projeto. Acho que isso pode mudar, dependendo de como viermos a entregar o produto final. Então podemos pensar nessa explicação no final.

1.1.4 Cuidados com diretório

Se a gente ainda precisar ter algum tipo de preocupação quanto a isso. Acho que não.

1.1.5 Como rodar cada tipo de arquivo (markdown, shiny)

Não é trivial para quem não está acostumado… usar runApp, knit… até mesmo o shift+enter para rodar as linhas de comando uma a uma

1.2 PARTE II – Carregando os dados para o R

1.2.1 Dados brutos

  • todas espécies/UCs – carrega_dados_1.Rmd
# carregar pacote
library(DT)

# carregar a função
source(
  corrigir_diretorio(
  corrige = 'R/carregar_dados_completos.R'
  )
)

# carregar dados para o R
dados_completos <- carregar_dados_completos() 


dados_completos |> 
  slice(1:500) |> 
  datatable(
    filter = list(
      position = "top"
    )
  )

1.2.2 Dados filtrados

  • por espécie/UC – carrega_dados_2.Rmd até o momento usado com o exemplo da cutia na Resex Tapajós-Arapiuns

1.3 Parte III – Transformando dados para Distance

1.3.1 Dados completos

  • todas espécies/UCs – transforma_para_distanceR.Rmd

1.3.2 Dados selecionados

Sistematizar os critérios utilizados para eliminar observações (linhas).

  • espécies validadas

1.4 Quantas observações foram validadas para quais níveis taxonômicos?

n_sp_validada <- dados_completos |> 
  count(validation)

Foram selecionadas apenas as observações validadas ao nível de espécie, somando um total 20790 observações.

1.4.1 PARTE IV – Explorando os dados

1.4.2 Selecionando os melhores modelos de estudo de acordo com os dados

Critŕios:

  • espécies com maior volume de dados total
  • maior volume de dados por UC – exploração_01.nb.html (acho que o .Rmd para gerar esse html não está na pasta Monitora). Eu tinha gostado bastante desse documento, com as tabelas dinâmicas. Talvez dê para selecionar as perguntas que são válidas de deixar/ tirar/ incluir.

WWF - Projeto Monitora

1.4.2.1 Exploração de dados

1.4.2.2 Informações básicas

1.4.2.3 Quantas unidades de conservação ao todo?

source(
  corrigir_diretorio(
    corrige = "R/contar_UCs.R"
  )
)

n_ucs <- contar_UCs(
  dados_selecionados
)

Os dados são provenientes de 40 unidades de conservação ao todo.

1.4.2.4 Quantas espécies ao todo?

source(
  corrigir_diretorio(
    corrige = "R/contar_sp.R"
  )
)

n_sp <- contar_sp(
  dados_completos
)

Foram coletados dados para 209 espécies.

1.4.2.5 Quantas observações por unidade de conservação ao todo?

As UC’s foram filtradas de acordo com o número de observações permitir a visualização.

A função de contagem de UC’s gerou 40 UC’s, mas só há observações para 38. Lembrar de verificar isso.

Adicionar o nome completo da UC na caixa interativa do gráfico. Identificar os plotes com subtítulos ex tentar adicionar título aos plotes

Tabela interativa com os dados completos de contagem de observações por UC.

dados_selecionados  |>  
  dplyr::count(uc_name, uc_name_abv) |> 
  DT::datatable(filter = list(position = "top"))

1.4.2.6 Quantas observações para cada espécie?

Tabela interativa para consulta do número de observações por espécie.

dados1 |>  
  dplyr::filter(validacao == "E") |> 
  dplyr::count(especie) |> 
  DT::datatable(filter = list(position = "top"))

1.4.2.7 Quais e quantas observações para cada espécie por unidades de conservação?

Tabela interativa para consulta do número de observações por espécie e por UC.

dados1 |>  
  dplyr::filter(validacao == "E") |> 
  dplyr::count(ucs, especie) |> 
  DT::datatable(filter = list(position = "top"))

1.4.2.8 Quantas unidades de conservação foram amostradas em cada ano?

1.4.2.9 Quantas observações foram realizadas por UC em cada ano?

Tabela interativa para consultar quantas observações foram realizadas por ano em cada UC

dados1 |>  
  dplyr::count(ano, ucs) |> 
  DT::datatable(filter = list(position = "top"))

1.4.2.10 Quantas observações para cada espécies por ano?

Tabela interativa para consultar quantas observações foram realizadas para cada espécie em cada ano

dados1 |>  
  dplyr::count(ano, especie) |> 
  DT::datatable(filter = list(position = "top"))

1.4.2.11 Quantas observações para cada espécies por UC e por ano?

Tabela interativa para consultar quantas observações foram realizadas para cada espécie em cada ano

dados1 |>  
  dplyr::count(ano, ucs, especie) |> 
  DT::datatable(filter = list(position = "top"))

1.4.2.12 Quantas observações para cada espécies por UC, por estação e por ano?

dados1 |>  
  dplyr::count(ano, season, uc_name, sp) |> 
  DT::datatable(filter = list(position = "top"))

1.4.3 Selecionando melhores modelos de estudo considerando estratificação espacial/temporal – se há suficiência amostral (60-80 observações) por estrato

  • Possíveis estratificações espaciais – EAs/UCs

                      - UCs/Espécies
    • Possíveis estratificações temporais – Espécie/UC/Ano

1.4.4 Avaliando distância de truncamento

  • Gráficos de distribuição das frequências de ocorrência x distância perpendicular. Arquivos gráfico-exploratorio1.Rmd e gráfico-exploratorio2.Rmd (eu não sei como você fez para incluir aquela linha vermelha com o valor de w no gráfico exploratório 2, mas ficou legal)

1.4.5 Distribuição de distâncias

# carregar dados_filtrados.R da pasta data para o R
dados_filtrados <- readr::read_rds(corrigir_diretorio(corrige = "data/dados_filtrados.rds")) 

# gerar o gráfico exploratório da distribuição de distâncias perpendiculares para a espécies Dasyrocta croconota na Resex Tapajós-Arapiuns
fig <- dados_filtrados |>
  # excluir NA's da variável distance
  tidyr::drop_na(distance) |> 
  grafico_exploratorio3()

fig

1.4.6 avaliando covariáveis

– As covariáveis devem ser pensadas de acordo com o grupo taxonômico. Espécies que formam grupos devem ter a covariável ‘size’.

As estratégias de estratificação podem ser substituídas por covariáveis também (estratos espaciais/ ano)

Como covariável temporal, pode se pensar em usar, além do ano, a estação do ano (season), o horário do dia (para animais que variam a atividade). O horário do dia pode ser convertido em tempo após nascer do sol (como no exemplo). Mas para isso é necessário criar essa variável no dataset. E não é trivial porque precisa saber o horário de nascer do sol em cada dia/local para calcular.

1.4.7 gerar gráficos distância x covariável

Exemplo de Gráficos de Marques et al. 2007

1.5 PARTE V – Ajustando os modelos

Esse trabalho do Marque et al. 2007 é uma boa referência de como usar as abordagens CDS global, CDS estratificada e MCDS.

Aqui, é possível testar alguns caminhos de modelos. A estratificação só faz sentido quando o volume de dados for grande. Ainda assim o uso de covariáveis pode substituir a estratificação. Pensar em como orientar o uso dessas abordagens

1.5.1 Modelos pela abordagem CDS – dados globais

  • função ds do Distance (argumentos básicos: truncation; key, adjustment, scale… estudar argumentos para ver se mais algum interessa)

1.5.2 Modelos pela abordagem CDS – dados estratificados

  • Aqui precisa ver direitinho os cuidados que precisa ter para ajustar as funções nos dados estratificados. Acho que faz em blocos. Vai aplicando os mesmos parâmetros para todos os estratos a cada modelo.

  • para cada estrato (espacial ou temporal) usar - função ds do Distance (argumentos básicos: truncation; key, adjustment, scale… estudar argumentos para ver se mais algum interessa)

1.5.3 Modelos pela abordagem MCDS – dados globais

Aqui não faz sentido estratificar

  • função ds do Distance (argumentos básicos: truncation; key, adjustment, scale… estudar argumentos para ver se mais algum interessa… para as covariáveis entra o argumento formula)

Dicas em Miller et al. 2019 sobre covariáveis (ver arquivo no driver).

1.6 PARTE VI – Avaliando os modelos

1.6.1 Ajuste dos modelos

  • função gof_ds

– para gerar Q-Q plots e testes associados

1.6.2 Selecionando modelos (AIC)

– função summarize_ds_models

DICAS EXTRAS DE MILLER et al. 2019

1.7 PARTE VII – PRODUTO FINAL

  • Como organizar

  • Interatividade

2 Criar expressões reativas

reactive() eventReactive()

observe() observeEvent()

reactiveVal() reactiveValues()

isolate()

3 Glossário

LS0tCnRpdGxlOiAiRXNib8OnbyBkbyBmbHV4byBkZSB0cmFiYWxobyBkZSBwcm9kdcOnw6NvIGRvcyBjw7NkaWdvcyIKZGF0ZTogIkNyaWFkbyBlbSAzMSBkZSBtYXLDp28gZGUgMjAyMywgYXR1YWxpemFkbyBlbSBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkIGRlICVCIGRlICVZJylgIgphdXRob3I6IAotIEx1Y2lhbmEgRnVzaW5hdHRvCi0gVml0b3IgQm9yZ2VzLUrDum5pb3IKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbjogdHJ1ZQogICAgCi0tLQoKYGBge3IgY29uZmlndXJhw6fDo28sIGluY2x1ZGU9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgY2FycmVnYXIgcGFjb3RlcwpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShmbGV4dGFibGUpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoRFQpCgojIGNhcnJlZ2FyIGFzIGZ1bsOnw7VlcyBkYSBwYXN0YSBSCiMgY2FycmVnYXIgZnVuw6fDo28gY29ycmlnaXJfZGlyZXRvcmlvLlIKc291cmNlKAogIHBhc3RlMCgKICAgIHN0cmluZ3I6OnN0cl9yZW1vdmUoCiAgICAgIGdldHdkKCksIAogICAgICAnZG9jJwogICAgKSwKICAgICJSL2NvcnJpZ2lyX2RpcmV0b3Jpby5SIgogICkKKSAKCiMgY2FycmVnYXIgZnVuw6fDo28gY2FycmVnYXJfZGFkb3NfZXhwbG9yYWNhby5SCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gIlIvY2FycmVnYXJfZGFkb3NfZXhwbG9yYWNhby5SIgogICkKKSAKCiMgY2FycmVnYXIgZnVuw6fDo28gZ3JhZmljb19leHDEum9yYXRvcmlvX2ludGVyYXRpdm8Kc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAiUi9ncmFmaWNvX2V4cGxvcmF0b3Jpb19pbnRlcmF0aXZvLlIiCiAgKQopIAoKIyBjYXJyZWdhciBkYWRvcyBkYSBwYXN0YSBkb2MKIyBjYXJyZWdhciBkYWRvc19jb21wbGV0b3MuUiBkYSBwYXN0YSBkb2MKZGFkb3NfY29tcGxldG9zIDwtIHJlYWRyOjpyZWFkX3JkcygKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gImRhdGEvZGFkb3NfY29tcGxldG9zLnJkcyIKICApCikgCgoKIyBjYXJyZWdhciBkYWRvc19maWx0cmFkb3MuUiBkYSBwYXN0YSBkYXRhIHBhcmEgbyBSCmRhZG9zX2ZpbHRyYWRvcyA8LSByZWFkcjo6cmVhZF9yZHMoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJkYXRhL2RhZG9zX2ZpbHRyYWRvcy5yZHMiCiAgKQopIAoKYGBgCgojIEVTQk/Dh08gRkxVWE8gREUgVFJBQkFMSE8gRE8gUFJPRFVUTyAyIC0gQ8OTRElHT1MKCiMjICpQQVJURSBJIOKAkyBDdWlkYWRvcyBhbnRlcyBkZSBjb21lw6dhciBhIHJvZGFyIG9zIGPDs2RpZ29zIG5vIFIqCgpQZW5zYXIgcXVhaXMgb3JpZW50YcOnw7VlcyBzw6NvIG1haXMgZ2VyYWlzIGUgcXVhaXMgc8OjbyBpbXBvcnRhbnRlcyBkZSBhY29tcGFuaGFyIGNhZGEgY8OzZGlnby4KCiMjIyAqUnN0dWRpby9QYWNvdGVzL3ZlcnPDtWVzL3Npc3RlbWFzIG9wZXJhY2lvbmFpcyoKClNvYnJlIG9zIHBhY290ZXMsIHNlcmlhIGJvbSB0ZXIgdW1hIGxpc3RpbmhhIGRlIOKAmGxpYnJhcnnigJkgbm8gaW7DrWNpbyBkZSBjYWRhIGPDs2RpZ28/ClRhbHZleiBjb20gdW1hIGJyZXZlIGV4cGxpY2HDp8OjbyBkbyBxdWUgY2FkYSBwYWNvdGUgZmF6LCB2ZXJzw6NvIG3DrW5pbWEuLi4gbsOjbyBzZWkuCgoqT0JTKjogZXNzYSB0YWJlbGEgw6kgdW1hIHJlZmVyw6puY2lhIHBhcmEgb2J0ZXJtb3MgYXMgdmVyc8O1ZXMgZG9zIHBhY290ZXMgYW8gZmluYWwgZG8gZGVzZW52b2x2aW1lbnRvIGRvIHNjcmlwdC4gRWxhIGVzdMOhIGF1dG9tYXRpemFkYSwgZW50w6NvIHF1YW5kbyB0ZXJtaW5hcm1vcyBlbGUgcHJlY2lzYW1vcyByZWZhemUtbG8gZGUgZm9ybWEgcXVlIG7Do28gZ2VyZSBtYWlzIG11ZGFuw6dhIG5hcyB2ZXJzw7VlcyAodGVtIHF1ZSBmYXplciBhIHRhYmVsYSBuYSBtw6NvIG1lc21vLi4uKS4KCmBgYHtyfQojIGNhcnJlZ2FyIHBhY290ZSBwYXJhIGZvcm1hdGFyIHRhYmVsYQpsaWJyYXJ5KGZsZXh0YWJsZSkKCiMgZ2VyYXIgaW5mb3JtYcOnw7VlcyBzb2JyZSBvcyBwYWNvdGVzIGNhcnJlZ2Fkb3MKaW5mbyA8LSBzZXNzaW9uSW5mbygpCgojIGdlcmFyIHRhYmVsYSBjb20gb3MgcGFjb3RlcyBlIHZlcnPDtWVzCnRpYmJsZTo6dHJpYmJsZSgKICB+UGFjb3RlcywgICAgICAgICAgICAgICAgICAgICAgICAgflZlcnPDo28sCiAgdmVyc2lvbiRsYW5ndWFnZSwgICAgICAgICAgICAgICAgIHZlcnNpb24kdmVyc2lvbi5zdHJpbmcsCiAgaW5mbyRvdGhlclBrZ3MkZHBseXIkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJGRwbHlyJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkRGlzdGFuY2UkUGFja2FnZSwgIGluZm8kb3RoZXJQa2dzJERpc3RhbmNlJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkRFQkUGFja2FnZSwgICAgICAgIGluZm8kb3RoZXJQa2dzJERUJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkZmxleHRhYmxlJFBhY2thZ2UsIGluZm8kb3RoZXJQa2dzJGZsZXh0YWJsZSRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHBsb3RseSRQYWNrYWdlLCAgICBpbmZvJG90aGVyUGtncyRwbG90bHkkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyRyZWFkciRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkcmVhZHIkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyR0aWJibGUkUGFja2FnZSwgICAgaW5mbyRvdGhlclBrZ3MkdGliYmxlJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkdGlkeXIkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHRpZHlyJFZlcnNpb24sCikgfD4gCiAgcWZsZXh0YWJsZSgpIHw+IAogIHNldF9jYXB0aW9uKAogICAgIlRhYmVsYSB4eCAtIGNvbmZpZ3VyYcOnw6NvIGRlIHBhY290ZXMgbmVjZXNzw6FyaW9zIGUgcmVzcGVjdGl2YXMgdmVyc8O1ZXMgbcOtbmltYXMgcXVlIGRldmVtIHNlciB1dGlsaXphZGFzIHBhcmEgcmVwcm9kdXppciBvcyBjw7NkaWdvcyIKICApCmBgYAoKCiMjIyAqQ3VpZGFkb3MgY29tIGEgcGxhbmlsaGEgLnhsc3ggcXVlIHNlcsOhIGltcG9ydGFkYSAocGFyYSBxdWUgbWFudGVuaGEgbyBwYWRyw6NvIGRhIHBsYW5pbGhhIGRlIHJlZmVyw6puY2lhIGRvIElDTUJpbykqIAoKQWxndW1hcyBmdW7Dp8O1ZXMgZm9yYW0gZXNjcml0YXMgcGFyYSBmdW5jaW9uYXIgdG9tYW5kbyBjb21vIGJhc2UgZGUgZGFkb3MgZGUgcmVmZXLDqm5jaWEgYSBwbGFuaWxoYSBlbSBmb3JtYXRvIGV4Y2VsIGBQbGFuaWxoYSBPZmljaWFsIGNvbnNvbGlkYWRhIGRlIE1hc3RvLWF2ZXMgMjAxNC0yMSBWYWxpZGFkYSBDRU1BVkUgQ1BCIENFTkFQLnhsc3hgIGRpc3BvbmliaWxpemFkYSBwZWxvIFByb2pldG8gTW9uaXRvcmEuIEVzdGFzIGZ1bsOnw7VlcyBjYXJyZWdhbSBvcyBkYWRvcyBlIGZhemVtIHVtYSBzw6lyaWUgZGUgdHJhbnNmb3JtYcOnw7VlcyBwYXJhIGRldm9sdmUtbG9zIG5vIGZvcm1hdG8gcGFkcm9uaXphZG8gZG8gcHJvZ3JhbWEgRElTVEFOQ0UgcGFyYSBXaW5kb3dzLiBQb3J0YW50bywgcGFyYSBnYXJhbnRpciBhIHJlcHJvZHV0aWJpbGlkYWRlIGRvcyBjw7NkaWdvcyBwcm9kdXppZG9zIGVtIHZlcnPDtWVzIGF0dWFsaXphZGFzIGRhIGJhc2UgZGUgZGFkb3MgZG8gTW9uaXRvcmEsIMOpIGltcG9ydGFudGUgdG9tYXIgYWxndW5zIGN1aWRhZG9zLiAKCk8gcHJpbWVpcm8gZSBtYWlzIGltcG9ydGFudGUgY3VpZGFkbyDDqSBtYW50ZXIgb3MgbWVzbW9zIG5vbWVzIGRhcyBjb2x1bmFzIGVtIHZlcnPDtWVzIGF0dWFsaXphZGFzIGRhIGJhc2UgZGUgZGFkb3MgZG8gTW9uaXRvcmEuIEFzIHByaW1laXJhcyBmdW7Dp8O1ZXMsIGFsw6ltIGRlIGNhcnJlZ2FyIG9zIGRhZG9zLCBhcGxpY2FtIHVtYSBzw6lyaWUgZGUgdHJhbnNmb3JtYcOnw7Vlcy4gT3Mgbm9tZXMgZGFzIGNvbHVuYXMgc8OjbyBhbHRlcmFkb3MsIGUgYSBlc3NhcyBzw6NvIGF0cmlidcOtZG9zIHRpcG9zIChkYXRhLCBjYXJhY3RlciwgZmF0b3IgLCBpbnRlaXJvIGUgbnVtw6lyaWNvKSwgbGluaGFzIHPDo28gZWxpbWluYWRhcyBlIG5vdmFzIGNvbHVuYXMgc8OjbyBnZXJlYWRhcy4gUGFyYSBleGVtcGxpZmljYXIsIHZlamEgbyBjw7NkaWdvIGFiYWl4by4gRWxlIGZvaSBlc2NyaXRvIHBhcmEgZXhlY3V0YXIgYXMgcHJpbWVpcmFzIHRyYW5zZm9ybWHDp8O1ZXMgbm9zIGRhZG9zIGUgY29uc3RpdHVpIG8gY29ycG8gZGEgZnVuw6fDo28gYGNhcnJlZ2FyX2RhZG9zX2ZpbHRyYWRvcygpYC4gCgpgYGB7cn0KIyBjYXJyZWdhciBwYWNvdGVzIHBhcmEgbWFuaXB1bGHDp8OjbyBkb3MgZGFkb3MKbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkeGwpCgojIGNhcnJlZ2FyIGZ1bsOnw6NvIGNvcnJpZ2lyX2RpcmV0b3Jpbwpzb3VyY2UoCiAgcGFzdGUwKAogICAgc3RyaW5ncjo6c3RyX3JlbW92ZSgKICAgICAgZ2V0d2QoKSwgCiAgICAgICdkb2MnCiAgICApLAogICAgIlIvY29ycmlnaXJfZGlyZXRvcmlvLlIiCiAgKQopIAoKIyBjYXJyZWdhciBhIGJhc2UgZGUgZGFkb3MgZG8gTW9uaXRvcmEKZGFkb3NfYnJ1dG9zIDwtIHJlYWRfZXhjZWwoCiAgcGF0aCA9IGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAiL2RhdGEtcmF3L1BsYW5pbGhhIE9maWNpYWwgY29uc29saWRhZGEgZGUgTWFzdG8tYXZlcyAyMDE0LTIxIFZhbGlkYWRhIENFTUFWRSBDUEIgQ0VOQVAueGxzeCIKICApLAogIHNoZWV0ID0gImRhZG9zIGJydXRvcyIKKQoKIyBnZXJhciBvIGRhdGEuZnJhbWUgZGVzZWphZG8KZGFkb3NfY29tcGxldG9zIDwtIGRhZG9zX2JydXRvcyB8PiAgCiAgIyBzZWxlY2lvbmFyIGFzIGNvbHVuYXMgbmVjZXNzw6FyaWFzIHBhcmEgYXMgYW5hbGlzZXMsIHBhZHJvbml6YW5kbyBvcyBub21lcyBwYXJhIG8gZm9ybWF0byBESVNUQU5DRQogIGRwbHlyOjpzZWxlY3QoCiAgICB1Y19jb2RlID0gQ0RVQywKICAgIHVjX25hbWUgPSBgTG9jYWwgLSBOb21lIGRhIFVuaWRhZGUgZGUgQ29uc2VydmHDp8Ojb2AsCiAgICBlYV9udW1iZXIgPSBgTsO6bWVybyBkYSBFc3Rhw6fDo28gQW1vc3RyYWxgLAogICAgZWFfbmFtZSA9IGBOb21lIGRhIEVBYCwKICAgIHNlYXNvbiA9IGBFc3Rhw6fDo28gZG8gYW5vYCwKICAgIHNhbXBsaW5nX2RheSA9IGBkYXRhIGRhIGFtb3N0cmFnZW1gLAogICAgZGF5X2VmZm9ydCA9IGBFc2ZvcsOnbyBkZSBhbW9zdHJhZ2VtIHRhbWFuaG8gZGEgdHJpbGhhIChtKWAsCiAgICBzcCA9IGBFc3DDqWNpZXMgdmFsaWRhZGFzIHBhcmEgYW7DoWxpc2UgZG8gSUNNQmlvYCwKICAgIGRpc3RhbmNlID0gYGRpc3TDom5jaWEgKG0pICAgICBkbyBhbmltYWwgZW0gcmVsYcOnw6NvIGEgdHJpbGhhYCwKICAgIGdyb3VwX3NpemUgPSBgbsKwIGRlIGFuaW1haXNgLAogICAgb2JzZXJ2YWRvcmVzID0gYG5vbWUgZG9zIG9ic2VydmFkb3Jlc2AKICApIHw+CiAgIyBhdHJpYnVpciBvcyB0aXBvcyBjb3JyZXRvcyDDoHMgY29sdW5hcyBlIGNyaWFyIG5vdmFzIGNvbHVuYXMKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIHVjX2NhdGVnb3J5ID0gc3RyaW5naTo6c3RyaV9leHRyYWN0X2ZpcnN0X3dvcmRzKAogICAgICB1Y19uYW1lCiAgICApLAogICAgIyBhYnJldmlhIG8gbm9tZSBkYXMgVUNzCiAgICB1Y19uYW1lX2FidiA9IGZvcmNhdHM6Omx2bHNfcmV2YWx1ZSgKICAgICAgdWNfbmFtZSwKICAgICAgbmV3X2xldmVscyA9IGMoCiAgICAgICAgIkVUTSIsICJFTSIsICJFTiIsICJFU0dUIiwgIkZKIiwgIlBDViIsICJQQSIsICJQU0JvYyIsICJQU0JvZCIsICJQU0MiLAogICAgICAgICJQU00iLCAiUFNDIiwgIlBTRCIsICJQU1AiLCAiUFNPIiwgIlBQTiIsICJQQ08iLCAiUEkiLCAiUEphw7oiLCAiUEp1ciIsCiAgICAgICAgIlBNUiIsICJQUyIsICJQViIsICJQQ0EiLCAiUE1UIiwgIlJHIiwgIlJKIiwgIlJUYXAiLCAiUlUiLCAiUkciLAogICAgICAgICJSVHJvbSIsICJSQVQiLCAiUkJBIiwgIlJDSSIsICJSQ00iLCAiUlJDIiwgIlJST1AiLCAiUklBIiwgIlJSQSIsICJSVEEiCiAgICAgICkKICAgICksCiAgICAgICMgYXRyaWJ1aXIgbyB0aXBvIGRhdGEgw6AgY29sdW5hIHNhbXBsaW5nX2RheQogICAgICB5ZWFyID0gbHVicmlkYXRlOjp5ZWFyKAogICAgICAgIHNhbXBsaW5nX2RheQogICAgICApLAogICAgICAjIGF0cmlidWlyIG8gdGlwbyBmYXRvciDDoHMgY29sdW5hcyBkbyB0aXBvIGNhcmFjdGVyCiAgICAgIGFjcm9zcygKICAgICAgICB3aGVyZSgKICAgICAgICAgIGlzLmNoYXJhY3RlcgogICAgICAgICksCiAgICAgICAgYXMuZmFjdG9yCiAgICAgICksCiAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgICBvYnNlcnZhZG9yZXMsIAogICAgICAgICIgZSAiLAogICAgICAgICIsICIKICAgICAgKSwKICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgogICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIG5vdm8sIAogICAgICAgICIgRSAiLAogICAgICAgICIsICIKICAgICAgKSwKICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgogICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIG5vdm8sIAogICAgICAgICIvIiwKICAgICAgICAiLCAiCiAgICAgICksCiAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgICBub3ZvLCAKICAgICAgICAiOyIsCiAgICAgICAgIiwgIgogICAgICApLAogICAgICAjIHN1YnN0aXR1aXIgc2VwYXJhZG9yZXMgZGUgbm9tZSBwb3IgIiwiCiAgICAgIG5vdm8gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiAgICAgICAgbm92bywgCiAgICAgICAgIiBhICIsCiAgICAgICAgIiwgIgogICAgICApIAogICAgKSB8PgogICMgdHJhbnNmb3JtYXIgb3Mgbm9tZXMgZG9zIG9ic2VydmFkb3JlcyBkYSBjb2x1bmEgbm92byBlbSBjb2x1bmFzIGluZGl2aWR1YWlzCnRpZHlyOjpzZXBhcmF0ZV93aWRlcl9kZWxpbSgKICBub3ZvLCAKICAiLCIsCiAgbmFtZXMgPSBjKAogICAgIm9iczEiLCAib2JzMiIsICJvYnMzIiwgIm9iczQiLCAib2JzNSIsICJvYnM2IgogICksCiAgdG9vX2ZldyA9ICJhbGlnbl9zdGFydCIKKSB8PiAKICAjIGdlcmFyIHVtYSBub3ZhIGNvbHVuYSBudW1iZXJfb2JzZXJ2ZXJzIGNvbSBvIG7Dum1lcm8gdG90YWwgZGUgb2JzZXJ2YWRvcmVzIGVtIHVtIG1lc21vIHRyYW5zZWN0bwogIGRwbHlyOjptdXRhdGUoCiAgICAjIHNlIG8gdmFsb3IgZGEgb2JzZXJ2YcOnw6NvIMOpIGRpZmVyZW50ZSBkZSBOQSwgc3Vic3RpdHVpciBwb3IgMSwgc2UgZm9yIE5BLCBzdWJzdGl0dWlyIHBvciAwCiAgICBvYnMxID0gaWZlbHNlKCFpcy5uYShvYnMxKSwgMSwgMCksCiAgICBvYnMyID0gaWZlbHNlKCFpcy5uYShvYnMyKSwgMSwgMCksCiAgICBvYnMzID0gaWZlbHNlKCFpcy5uYShvYnMzKSwgMSwgMCksCiAgICBvYnM0ID0gaWZlbHNlKCFpcy5uYShvYnM0KSwgMSwgMCksCiAgICBvYnM1ID0gaWZlbHNlKCFpcy5uYShvYnM1KSwgMSwgMCksCiAgICBvYnM2ID0gaWZlbHNlKCFpcy5uYShvYnM2KSwgMSwgMCksCiAgICAjIGdlcmEgbm92YSBjb2x1bmEgbnVtYmVyX29ic2VydmVycyBhIHBhcnRpciBkYSBzb21hIGRhcyBjb2x1bmFzIGRlIG9ic2VydmFkb3JlcyBpbmRpdmlkdWFpcwogICAgbnVtYmVyX29ic2VydmVycyA9IG9iczEgKyBvYnMyICsgb2JzMyArIG9iczQgKyBvYnM1ICsgb2JzNgogICkgfD4gCiAgIyBhZ3J1cGFyIG9zIGRhZG9zIHBlbGFzIGNvbHVuYXMgZWFfbmFtZSBlIHNhbXBsaW5nX2RheQogIGdyb3VwX2J5KAogICAgZWFfbmFtZSwgCiAgICBzYW1wbGluZ19kYXkKICApIHw+IAogICMgYW5pbmhhciBhcyBvYnNlcnZhw6fDtWVzIGFncnVwYWRhcyB1ZW0gbGlzdGFzCiAgbmVzdCgpIHw+IAogICMgY29tcGxldGFyIGNvbSBvIHZhbG9yIGNvcnJldG8gYXMgbGluaGFzIHZhemlhcyBkYXMgZGEgdmFyacOhdmVsIGRheV9lZmZvcnQKICBtdXRhdGUoCiAgICBkYXlfZWZmb3J0MiA9IHB1cnJyOjptYXAoCiAgICAgIGRhdGEsIFwoLngpIHJlcCgKICAgICAgICAueCRkYXlfZWZmb3J0WwogICAgICAgICAgIWlzLm5hKAogICAgICAgICAgICAueCRkYXlfZWZmb3J0CiAgICAgICAgICApCiAgICAgICAgXVsxXQogICAgICApCiAgICApCiAgKSB8PiAKICAjIGRlc2FuaWhhciBvcyBkYWRvcwogIHVubmVzdCgKICAgIGMoCiAgICAgIGRhdGEsIAogICAgICBkYXlfZWZmb3J0MgogICAgKQogICkgfD4gCiAgIyBkZXNhZ3J1cGFyIG9zIGRhZG9zCiAgdW5ncm91cCgpIHw+IAogICMgc2VsZWNpb25hciBhcyBjb2x1bmFzIGRlc2VqYWRhcyBlIGV4Y2x1aXIgYXMgaW5kZXNlamFkYXMKICBzZWxlY3QoCiAgICB0aWR5c2VsZWN0OjpzdGFydHNfd2l0aChjKCJ1YyIsICJlYSIpKSwKICAgIHNlYXNvbiwKICAgIHllYXIsCiAgICBzYW1wbGluZ19kYXksCiAgICBkYXlfZWZmb3J0ID0gZGF5X2VmZm9ydDIsCiAgICBzcDpudW1iZXJfb2JzZXJ2ZXJzLAogICAgLWRheV9lZmZvcnQsCiAgICAtdGlkeXNlbGVjdDo6c3RhcnRzX3dpdGgoIm9icyIpCiAgKSB8PgogICMgZmlsdHJhciBvcyBkYWRvcyBwZWxhIFVDIGUgZXNww6ljaWUgZGVzZWphZGFzCiAgICBkcGx5cjo6ZmlsdGVyKAogICAgICB1Y19uYW1lID09ICJSZXNleCBUYXBhasOzcy1BcmFwaXVucyIsCiAgICAgIHNwID09ICJEYXN5cHJvY3RhIGNyb2Nvbm90YSIKICAgICkgfD4gCiAgcmVsb2NhdGUoCiAgICB1Y19jYXRlZ29yeSwKICAgIC5iZWZvcmUgPSBgTG9jYWwgLSBOb21lIGRhIFVuaWRhZGUgZGUgQ29uc2VydmHDp8Ojb2AKICApIHw+IAogIHJlbG9jYXRlKAogICAgdWNfbmFtZV9hYnYsCiAgICAuYWZ0ZXIgPSBgTG9jYWwgLSBOb21lIGRhIFVuaWRhZGUgZGUgQ29uc2VydmHDp8Ojb2AKICApCgojIGdlcmFyIHRhYmVsYSBkaW7Dom1pY2EgZG9zIGRhZG9zIGJydXRvcwpkYWRvc19jb21wbGV0b3MgfD4gCiAgc2xpY2UoMToxMDApIHw+IAogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiKSkKYGBgCgpPIHRyZWNobyBkbyBjw7NkaWdvIHF1ZSB2YWkgZGEgbGluaGEgMTAxIGEgMTEzIHNlcnZlIHNlbGVjaW9uYXIgYXBlbmFzIGFzIGNvbHVuYXMgZGUgaW50ZXJlc3NlIHByZXNlbnRlIG5vcyBkYWRvcyBvcmlnaW5haXMuIE5vdGUgcXVlIG9zIG5vbWVzIGRhcyBwbGFuaWxoYXMgb3JpZ2luYWlzIGNvbnN0YW0gbmVzc2UgdHJlY2hvLiBDYXNvIG8gbm9tZSBkZSBxdWFscXVlIHVtYSBkZXNzYXMgY29sdW5hcyBzZWphIGFsdGVyYWRvIGEgZnVuw6fDo28gZGVpeGFyw6EgZGUgZnVuY2lvbmFyLgoKT3V0cm8gYXNwZWN0byBpbXBvcnRhbnRlIMOpIGEgcHJlc2Vuw6dhIGRlIG9ic2VydmHDp8O1ZXMgbsOjbyBwcmVlbmNoaWRhcyAoZXguIGPDqWx1bGFzIHZhemlhcykgbm9zIGRhZG9zIG9yaWdpbmFpcy4gQSBmdW7Dp8OjbyBmb2kgZGVzZW5oYSBwYXJhIHJlc29sdmVyIGFsZ3VucyBwcm9ibGVtYXMgcHJlc2VudGVzIG5vcyBkYWRvcyBvcmlnaW5haXMuIFBvciBleGVtcGxvLCBuYXMgbyB0cmVjaG8gZG8gY8OzZGlnbyBkYXMgbGluaGFzIHh4IGEgeHggYXMgb2JzZXJ2YcOnw7VlcyB2YXppYXMgKGBOQWBzKSBzw6NvIHN1YnN0aXR1aWRhcyBwZWxvIHZhbG9yIGNvcnJldG8gbmEgY29sdW5hIGBkYXlfZWZmb3J0YC4gRXNzYSBjb3JyZcOnw6NvIGNvbnRpbm51YXLDoSBzZW5kbyByZWFsaXphZGEgZW0gdmVyc8O1ZXMgYXR1YWxpemFkYXMgZG9zIGRhZG9zIGRvIE1vbml0b3JhLiBQb3LDqW0sIHNlIG91dHJhcyBjb2x1bmFzIGFsw6ltIGRhcyBxdWUgZXN0w6NvIHNlbmRvIGNvcnJpZ2lkYXMgcG9zc3VpcmVtIG9ic2VydmHDp8O1ZXMgdmF6aWFzIG9zIGRhZG9zIHNlcsOjbyBjYXJyZWdhZG9zIGUgdHJhbnNmb3JtYWRvcywgcG9yw6ltIG91dHJhcyBmdW7Dp8O1ZXMgcG9kZW0gdGVyIG8gc2V1IGZ1bmNpb25hbWVudG8gY29tcHJvbWV0aWRvLiBQb3IgZXhlbXBsby4uLiAoZnVuw6fDtWVzIGRlIHZpc3VhbGl6YcOnw6NvIGUgZG8gcGFjb3RlIGRpc3RhbmNlIHF1ZSBwb2RlbSBuYcO1IGZ1bmNpb25hciBkZXZpZG8gYSBhdXPDqm5jaWEgZGUgb2JzZXJ2YcOnw6NvKQoKT3V0cm9zIGN1aWRhZG9zLi4uCgpJbWFnaW5hbmRvIHF1ZSBhIHBsYW5pbGhhIGRlIGRhZG9zIGRvIG1vbml0b3JhIMOpIGFsZ28gZGluw6JtaWNvLCBxdWUgbyBub21lIGRhcyBjb2x1bmFzIHBvZGUgc2VyIGVkaXRhZG8uLi4KCiMjIyAqQ29tbyBhYnJpciBvcyBhcnF1aXZvczogY29tbyBzYWx2YXIgZSBkZXNjb21wYWN0YXIgYSBwYXN0YS4gQWJyaXIgcHJvamV0byoKClVtIHBhc3NvIGEgcGFzc28gZGUgY29tbyBzYWx2YXIgYXJxdWl2byBjb20gb3MgY8OzZGlnb3MgZSBhYnJpci4uIFBvciBleGVtcGxvLCBkYSBmb3JtYSBjb21vIGVzdMOhIMOpIGludGVyZXNzYW50ZSBkZXNjb21wYWN0YXIgYSBwYXN0YSBlIGFjZXNzYXIgb3MgYXJxdWl2b3MgYWJyaW5kbyBvIHByb2pldG8uIEFjaG8gcXVlIGlzc28gcG9kZSBtdWRhciwgZGVwZW5kZW5kbyBkZSBjb21vIHZpZXJtb3MgYSBlbnRyZWdhciBvIHByb2R1dG8gZmluYWwuIEVudMOjbyBwb2RlbW9zIHBlbnNhciBuZXNzYSBleHBsaWNhw6fDo28gbm8gZmluYWwuCgojIyMgKkN1aWRhZG9zIGNvbSBkaXJldMOzcmlvKgoKU2UgYSBnZW50ZSBhaW5kYSBwcmVjaXNhciB0ZXIgYWxndW0gdGlwbyBkZSBwcmVvY3VwYcOnw6NvIHF1YW50byBhIGlzc28uIEFjaG8gcXVlIG7Do28uCgojIyMgKkNvbW8gcm9kYXIgY2FkYSB0aXBvIGRlIGFycXVpdm8gKG1hcmtkb3duLCBzaGlueSkqCgpOw6NvIMOpIHRyaXZpYWwgcGFyYSBxdWVtIG7Do28gZXN0w6EgYWNvc3R1bWFkby4uLiB1c2FyIHJ1bkFwcCwga25pdC4uLiBhdMOpIG1lc21vIG8gc2hpZnQrZW50ZXIgcGFyYSByb2RhciBhcyBsaW5oYXMgZGUgY29tYW5kbyB1bWEgYSB1bWEKCiMjICpQQVJURSBJSSDigJMgQ2FycmVnYW5kbyBvcyBkYWRvcyBwYXJhIG8gUioKCiMjIyAqRGFkb3MgYnJ1dG9zKgoKLSB0b2RhcyBlc3DDqWNpZXMvVUNzIOKAkyBjYXJyZWdhX2RhZG9zXzEuUm1kCmBgYHtyfQojIGNhcnJlZ2FyIHBhY290ZQpsaWJyYXJ5KERUKQoKIyBjYXJyZWdhciBhIGZ1bsOnw6NvCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgY29ycmlnZSA9ICdSL2NhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcy5SJwogICkKKQoKIyBjYXJyZWdhciBkYWRvcyBwYXJhIG8gUgpkYWRvc19jb21wbGV0b3MgPC0gY2FycmVnYXJfZGFkb3NfY29tcGxldG9zKCkgCgoKZGFkb3NfY29tcGxldG9zIHw+IAogIHNsaWNlKDE6NTAwKSB8PiAKICBkYXRhdGFibGUoCiAgICBmaWx0ZXIgPSBsaXN0KAogICAgICBwb3NpdGlvbiA9ICJ0b3AiCiAgICApCiAgKQpgYGAKCgojIyMgKkRhZG9zIGZpbHRyYWRvcyoKCi0gcG9yIGVzcMOpY2llL1VDIOKAkyBjYXJyZWdhX2RhZG9zXzIuUm1kCmF0w6kgbyBtb21lbnRvIHVzYWRvIGNvbSBvIGV4ZW1wbG8gZGEgY3V0aWEgbmEgUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMKCmBgYHtyfQojIGNhcnJlZ2FyIGEgZnVuw6fDo28Kc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgICBjb3JyaWdlID0gJ1IvY2FycmVnYXJfZGFkb3NfZmlsdHJhZG9zLlInCiAgKQogICkKCiMgY2FycmVnYXIgZGFkb3MgcGFyYSBvIFIKZGFkb3NfZmlsdHJhZG9zIDwtIGNhcnJlZ2FyX2RhZG9zX2ZpbHRyYWRvcygKICBkYWRvcyA9IGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAgJ2RhdGEtcmF3L2RhZG9zLWJydXRvcy54bHN4JwogICksCiAgbm9tZV91YyA9ICJSZXNleCBUYXBhasOzcy1BcmFwaXVucyIsCiAgbm9tZV9zcCA9ICJEYXN5cHJvY3RhIGNyb2Nvbm90YSIKKQoKZGFkb3NfZmlsdHJhZG9zIHw+IAogIGRhdGF0YWJsZSgKICAgIGZpbHRlciA9IGxpc3QoCiAgICAgIHBvc2l0aW9uID0gInRvcCIKICAgICkKICApCmBgYAoKIyMgKlBhcnRlIElJSSDigJMgVHJhbnNmb3JtYW5kbyBkYWRvcyBwYXJhIERpc3RhbmNlKgoKIyMjICpEYWRvcyBjb21wbGV0b3MqCgotIHRvZGFzIGVzcMOpY2llcy9VQ3Mg4oCTIHRyYW5zZm9ybWFfcGFyYV9kaXN0YW5jZVIuUm1kCgpgYGB7cn0KIyBjYXJyZWdhciBhcyBmdW7Dp8O1ZXMKc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAiUi9jYXJyZWdhcl9kYWRvc19jb21wbGV0b3MuUiIKICApCiAgKSAKCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gIlIvdHJhbnNmb3JtYV9wYXJhX2Rpc3RhbmNlUi5SIgogICkKKQoKIyBjYXJyZWdhciBkYWRvcyBwYXJhIG8gUgpkYWRvc19jb21wbGV0b3MgPC0gY2FycmVnYXJfZGFkb3NfY29tcGxldG9zKAogIGRhZG9zID0gY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJkYXRhLXJhdy9kYWRvcy1icnV0b3MueGxzeCIKICApCiAgKQoKIyB0cmFuc2Zvcm1hciBvcyBkYWRvcyBwYXJhIG8gZm9ybWF0byBkbyBEaXN0YW5jZQpkYWRvc19kaXN0YW5jZVJfY29tcGxldG8gPC0gdHJhbnNmb3JtYV9wYXJhX2Rpc3RhbmNlUigKICBkYWRvc19jb21wbGV0b3MKKQoKZGFkb3NfZGlzdGFuY2VSX2NvbXBsZXRvIHw+IAogIHNsaWNlKDE6NTAwKSB8PiAKICBkYXRhdGFibGUoCiAgICBmaWx0ZXIgPSBsaXN0KAogICAgICBwb3NpdGlvbiA9ICJ0b3AiCiAgICApCiAgKQpgYGAKCgpgYGB7cn0KIyBjYXJyZWdhciBhcyBmdW7Dp8O1ZXMKc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICBjb3JyaWdlID0gIlIvdHJhbnNmb3JtYV9wYXJhX2Rpc3RhbmNlUl9jb3ZhcmlhdmVpcy5SIgopCikKCiMgY2FycmVnYXIgZGFkb3MgcGFyYSBvIFIKZGFkb3NfZmlsdHJhZG9zIDwtIHJlYWRfcmRzKAogIGZpbGUgPSBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gImRhdGEvZGFkb3NfZmlsdHJhZG9zLnJkcyIKICApCiAgKQoKIyB0cmFuc2Zvcm1hciBvcyBkYWRvcyBwYXJhIG8gZm9ybWF0byBkbyBEaXN0YW5jZQpkYWRvc19kaXN0YW5jZVJfY292YXJpYXZlaXMgPC0gdHJhbnNmb3JtYV9wYXJhX2Rpc3RhbmNlUl9jb3ZhcmlhdmVpcygKICBkYWRvcyA9IGRhZG9zX2ZpbHRyYWRvcwopCgpkYWRvc19kaXN0YW5jZVJfY292YXJpYXZlaXMgfD4gCiAgc2xpY2UoMTo1MDApIHw+IAogIGRhdGF0YWJsZSgKICAgIGZpbHRlciA9IGxpc3QoCiAgICAgIHBvc2l0aW9uID0gInRvcCIKICAgICkKICApCmBgYAoKIyMjICpEYWRvcyBzZWxlY2lvbmFkb3MqIAoKU2lzdGVtYXRpemFyIG9zIGNyaXTDqXJpb3MgdXRpbGl6YWRvcyBwYXJhIGVsaW1pbmFyIG9ic2VydmHDp8O1ZXMgKGxpbmhhcykuCgotIGVzcMOpY2llcyB2YWxpZGFkYXMKLSAuLi4KCiMjIFF1YW50YXMgb2JzZXJ2YcOnw7VlcyBmb3JhbSB2YWxpZGFkYXMgcGFyYSBxdWFpcyBuw612ZWlzIHRheG9uw7RtaWNvcz8KCmBgYHtyfQpuX3NwX3ZhbGlkYWRhIDwtIGRhZG9zX2NvbXBsZXRvcyB8PiAKICBjb3VudCh2YWxpZGF0aW9uKQpgYGAKCkZvcmFtIHNlbGVjaW9uYWRhcyBhcGVuYXMgYXMgb2JzZXJ2YcOnw7VlcyB2YWxpZGFkYXMgYW8gbsOtdmVsIGRlIGVzcMOpY2llLCBzb21hbmRvIHVtIHRvdGFsIGByIG5fc3BfdmFsaWRhZGEkblsxXWAgb2JzZXJ2YcOnw7Vlcy4KCmBgYHtyfQojIGNhcnJlZ2FyIGFzIGZ1bsOnw7Vlcwpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2NhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcy5SIgogICkKICApIApzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2dyYWZpY29fbl9zcF92YWxpZGFkYXMuUiIKICApCikKCiMgY2FycmVnYXIgZGFkb3MgcGFyYSBvIFIKZGFkb3NfY29tcGxldG9zIDwtIGNhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcygpCgojIGdlcmFyIGdyw6FmaWNvIGNvbSBuw7ptZXJvIG9ic2VydmHDp8O1ZXMgdmFsaWRhZGFzIHBhcmEgY2FkYSBuw612ZWwgdGF4b27DtG1pY28KZ3JhZmljb19uX3NwX3ZhbGlkYWRhcygpCmBgYAoKYGBge3J9CiMgY2FycmVnYXIgZnVuw6fDo28gY2FycmVnYXIgZGFkb3Mgc2VsZWNpb25hZG9zCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gIlIvY2FycmVnYXJfZGFkb3Nfc2VsZWNpb25hZG9zLlIiCiAgKQopCgojIGdlcmFyIHRhYmVsYSBkZSBkYWRvcyBzZWxlY2lvbmFkb3MKZGFkb3Nfc2VsZWNpb25hZG9zIDwtIGNhcnJlZ2FyX2RhZG9zX3NlbGVjaW9uYWRvcygpCgpkYWRvc19zZWxlY2lvbmFkb3MgfD4gCiAgc2xpY2UoMTo1MDApIHw+IAogIGRhdGF0YWJsZSgKICAgIGZpbHRlciA9IGxpc3QoCiAgICAgIHBvc2l0aW9uID0gInRvcCIKICAgICkKICApCmBgYAoKIyMjICpQQVJURSBJViDigJMgRXhwbG9yYW5kbyBvcyBkYWRvcyoKCiMjIyAqU2VsZWNpb25hbmRvIG9zIG1lbGhvcmVzIG1vZGVsb3MgZGUgZXN0dWRvIGRlIGFjb3JkbyBjb20gb3MgZGFkb3MqCgpDcml0xZVpb3M6CgotIGVzcMOpY2llcyBjb20gbWFpb3Igdm9sdW1lIGRlIGRhZG9zIHRvdGFsCi0gbWFpb3Igdm9sdW1lIGRlIGRhZG9zIHBvciBVQwog4oCTICBleHBsb3Jhw6fDo29fMDEubmIuaHRtbCAoYWNobyBxdWUgbyAuUm1kIHBhcmEgZ2VyYXIgZXNzZSBodG1sIG7Do28gZXN0w6EgbmEgcGFzdGEgTW9uaXRvcmEpLiBFdSB0aW5oYSBnb3N0YWRvIGJhc3RhbnRlIGRlc3NlIGRvY3VtZW50bywgY29tIGFzIHRhYmVsYXMgZGluw6JtaWNhcy4gVGFsdmV6IGTDqiBwYXJhIHNlbGVjaW9uYXIgYXMgcGVyZ3VudGFzIHF1ZSBzw6NvIHbDoWxpZGFzIGRlIGRlaXhhci8gdGlyYXIvIGluY2x1aXIuCgpXV0YgLSBQcm9qZXRvIE1vbml0b3JhCgojIyMjICpFeHBsb3Jhw6fDo28gZGUgZGFkb3MqCgojIyMjICpJbmZvcm1hw6fDtWVzIGLDoXNpY2FzKgoKIyMjIyAqUXVhbnRhcyB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFvIHRvZG8/KgoKYGBge3Igbl9kZV91Y3N9CnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gIlIvY29udGFyX1VDcy5SIgogICkKKQoKbl91Y3MgPC0gY29udGFyX1VDcygKICBkYWRvc19zZWxlY2lvbmFkb3MKKQpgYGAKCk9zIGRhZG9zIHPDo28gcHJvdmVuaWVudGVzIGRlIGByIG5fdWNzYCB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFvIHRvZG8uCgojIyMjICpRdWFudGFzIGVzcMOpY2llcyBhbyB0b2RvPyoKCmBgYHtyfQpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2NvbnRhcl9zcC5SIgogICkKKQoKbl9zcCA8LSBjb250YXJfc3AoCiAgZGFkb3NfY29tcGxldG9zCikKYGBgCgpGb3JhbSBjb2xldGFkb3MgZGFkb3MgcGFyYSBgciBuX3NwYCBlc3DDqWNpZXMuCgojIyMjICpRdWFudGFzIG9ic2VydmHDp8O1ZXMgcG9yIHVuaWRhZGUgZGUgY29uc2VydmHDp8OjbyBhbyB0b2RvPyoKCkFzIFVDJ3MgZm9yYW0gZmlsdHJhZGFzIGRlIGFjb3JkbyBjb20gbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcGVybWl0aXIgYSB2aXN1YWxpemHDp8Ojby4KCkEgZnVuw6fDo28gZGUgY29udGFnZW0gZGUgVUMncyBnZXJvdSA0MCBVQydzLCBtYXMgc8OzIGjDoSBvYnNlcnZhw6fDtWVzIHBhcmEgMzguICpMZW1icmFyIGRlIHZlcmlmaWNhciBpc3NvKi4KCmBgYHtyfQojIGNhcnJlZ2FyIGZ1bsOnw7Vlcwpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2NvbnRhcl9vYnNfVUMuUiIKICApCikKCm5fb2JzX3VjIDwtIGNvbnRhcl9vYnNfVUMoKQoKbl9vYnNfdWMgfD4gCiAgZGF0YXRhYmxlKGZpbHRlcj0gbGlzdCgKICAgIHBvc2l0aW9uID0gInRvcCIKICApCiAgKQpgYGAKCipBZGljaW9uYXIgbyBub21lIGNvbXBsZXRvIGRhIFVDIG5hIGNhaXhhIGludGVyYXRpdmEgZG8gZ3LDoWZpY28qLgoqSWRlbnRpZmljYXIgb3MgcGxvdGVzIGNvbSBzdWJ0w610dWxvcyBleCB0ZW50YXIgYWRpY2lvbmFyIHTDrXR1bG8gYW9zIHBsb3RlcyoKCmBgYHtyLCBmaWcuaGVpZ2h0PTIwfQojIGNhcnJlZ2FyIGZ1bsOnw7Vlcwpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2dyYWZpY29fbl9vYnNfVUNfaW50ZXJhdGl2by5SIgogICkKKQoKIyBwbG90YXIgbyBvIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwb3IgVUMKZGFkb3Nfc2VsZWNpb25hZG9zIHw+IAogIGdyYWZpY29fbl9vYnNfVUNfaW50ZXJhdGl2bygpCmBgYAoKVGFiZWxhIGludGVyYXRpdmEgY29tIG9zIGRhZG9zIGNvbXBsZXRvcyBkZSBjb250YWdlbSBkZSBvYnNlcnZhw6fDtWVzIHBvciBVQy4KYGBge3J9CmRhZG9zX3NlbGVjaW9uYWRvcyAgfD4gIAogIGRwbHlyOjpjb3VudCh1Y19uYW1lLCB1Y19uYW1lX2FidikgfD4gCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIpKQpgYGAKCiMjIyMgKlF1YW50YXMgb2JzZXJ2YcOnw7VlcyBwYXJhIGNhZGEgZXNww6ljaWU/KgoKVGFiZWxhIGludGVyYXRpdmEgcGFyYSBjb25zdWx0YSBkbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIGVzcMOpY2llLgpgYGB7cn0KZGFkb3MxIHw+ICAKICBkcGx5cjo6ZmlsdGVyKHZhbGlkYWNhbyA9PSAiRSIpIHw+IAogIGRwbHlyOjpjb3VudChlc3BlY2llKSB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKIyMjIyAqUXVhaXMgZSBxdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llIHBvciB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvPyoKClRhYmVsYSBpbnRlcmF0aXZhIHBhcmEgY29uc3VsdGEgZG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBlc3DDqWNpZSBlIHBvciBVQy4KYGBge3J9CmRhZG9zMSB8PiAgCiAgZHBseXI6OmZpbHRlcih2YWxpZGFjYW8gPT0gIkUiKSB8PiAKICBkcGx5cjo6Y291bnQodWNzLCBlc3BlY2llKSB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKIyMjIyAqUXVhbnRhcyB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGZvcmFtIGFtb3N0cmFkYXMgZW0gY2FkYSBhbm8/KgoKYGBge3IsIGVjaG89RkFMU0V9CmRhZG9zMSB8PiAgCiAgZHBseXI6OmNvdW50KGFubywgdWNzKSB8PiAgCiAgZHBseXI6Omdyb3VwX2J5KGFubykgfD4gIAogIGRwbHlyOjpjb3VudCh1Y3MpIHw+ICAKICBkcGx5cjo6c3VtbWFyaXNlKG5fdWNzID0gc3VtKG4pKQpgYGAKCiMjIyMgKlF1YW50YXMgb2JzZXJ2YcOnw7VlcyBmb3JhbSByZWFsaXphZGFzIHBvciBVQyBlbSBjYWRhIGFubz8qCgpUYWJlbGEgaW50ZXJhdGl2YSBwYXJhIGNvbnN1bHRhciBxdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gcmVhbGl6YWRhcyBwb3IgYW5vIGVtIGNhZGEgVUMKYGBge3J9CmRhZG9zMSB8PiAgCiAgZHBseXI6OmNvdW50KGFubywgdWNzKSB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKIyMjIyBRdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgYW5vPwoKVGFiZWxhIGludGVyYXRpdmEgcGFyYSBjb25zdWx0YXIgcXVhbnRhcyBvYnNlcnZhw6fDtWVzIGZvcmFtIHJlYWxpemFkYXMgcGFyYSBjYWRhIGVzcMOpY2llIGVtIGNhZGEgYW5vCmBgYHtyfQpkYWRvczEgfD4gIAogIGRwbHlyOjpjb3VudChhbm8sIGVzcGVjaWUpIHw+IAogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiKSkKYGBgCgojIyMjICpRdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgVUMgZSBwb3IgYW5vPyoKClRhYmVsYSBpbnRlcmF0aXZhIHBhcmEgY29uc3VsdGFyIHF1YW50YXMgb2JzZXJ2YcOnw7VlcyBmb3JhbSByZWFsaXphZGFzIHBhcmEgY2FkYSBlc3DDqWNpZSBlbSBjYWRhIGFubwoKYGBge3J9CmRhZG9zMSB8PiAgCiAgZHBseXI6OmNvdW50KGFubywgdWNzLCBlc3BlY2llKSB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKIyMjIyAqUXVhbnRhcyBvYnNlcnZhw6fDtWVzIHBhcmEgY2FkYSBlc3DDqWNpZXMgcG9yIFVDLCBwb3IgZXN0YcOnw6NvIGUgcG9yIGFubz8qCgpgYGB7cn0KZGFkb3MxIHw+ICAKICBkcGx5cjo6Y291bnQoYW5vLCBzZWFzb24sIHVjX25hbWUsIHNwKSB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKIyMjICpTZWxlY2lvbmFuZG8gbWVsaG9yZXMgbW9kZWxvcyBkZSBlc3R1ZG8gY29uc2lkZXJhbmRvIGVzdHJhdGlmaWNhw6fDo28gZXNwYWNpYWwvdGVtcG9yYWwg4oCTIHNlIGjDoSBzdWZpY2nDqm5jaWEgYW1vc3RyYWwgKDYwLTgwIG9ic2VydmHDp8O1ZXMpIHBvciBlc3RyYXRvKgoKLSBQb3Nzw612ZWlzIGVzdHJhdGlmaWNhw6fDtWVzIGVzcGFjaWFpcyDigJMgRUFzL1VDcwoKCQkJCQkgICAgLSBVQ3MvRXNww6ljaWVzCgoJLSBQb3Nzw612ZWlzIGVzdHJhdGlmaWNhw6fDtWVzIHRlbXBvcmFpcyDigJMgRXNww6ljaWUvVUMvQW5vIAoKIyMjICpBdmFsaWFuZG8gZGlzdMOibmNpYSBkZSB0cnVuY2FtZW50byAqCgotIEdyw6FmaWNvcyBkZSBkaXN0cmlidWnDp8OjbyBkYXMgZnJlcXXDqm5jaWFzIGRlIG9jb3Jyw6puY2lhIHggZGlzdMOibmNpYSBwZXJwZW5kaWN1bGFyLiBBcnF1aXZvcyBncsOhZmljby1leHBsb3JhdG9yaW8xLlJtZCBlIGdyw6FmaWNvLWV4cGxvcmF0b3JpbzIuUm1kIChldSBuw6NvIHNlaSBjb21vIHZvY8OqIGZleiBwYXJhIGluY2x1aXIgYXF1ZWxhIGxpbmhhIHZlcm1lbGhhIGNvbSBvIHZhbG9yIGRlIHcgbm8gZ3LDoWZpY28gZXhwbG9yYXTDs3JpbyAyLCBtYXMgZmljb3UgbGVnYWwpCgojIyMgKkRpc3RyaWJ1acOnw6NvIGRlIGRpc3TDom5jaWFzKgoKYGBge3IgZGlzdHJpYnVpY2FvX2RzaXRhbmNpYSwgd2FybmluZz1GQUxTRX0KIyBjYXJyZWdhciBkYWRvc19maWx0cmFkb3MuUiBkYSBwYXN0YSBkYXRhIHBhcmEgbyBSCmRhZG9zX2ZpbHRyYWRvcyA8LSByZWFkcjo6cmVhZF9yZHMoY29ycmlnaXJfZGlyZXRvcmlvKGNvcnJpZ2UgPSAiZGF0YS9kYWRvc19maWx0cmFkb3MucmRzIikpIAoKIyBnZXJhciBvIGdyw6FmaWNvIGV4cGxvcmF0w7NyaW8gZGEgZGlzdHJpYnVpw6fDo28gZGUgZGlzdMOibmNpYXMgcGVycGVuZGljdWxhcmVzIHBhcmEgYSBlc3DDqWNpZXMgRGFzeXJvY3RhIGNyb2Nvbm90YSBuYSBSZXNleCBUYXBhasOzcy1BcmFwaXVucwpmaWcgPC0gZGFkb3NfZmlsdHJhZG9zIHw+CiAgIyBleGNsdWlyIE5BJ3MgZGEgdmFyacOhdmVsIGRpc3RhbmNlCiAgdGlkeXI6OmRyb3BfbmEoZGlzdGFuY2UpIHw+IAogIGdyYWZpY29fZXhwbG9yYXRvcmlvMygpCgpmaWcKYGBgCgojIyMgKmF2YWxpYW5kbyBjb3ZhcmnDoXZlaXMqCgrigJMgQXMgY292YXJpw6F2ZWlzIGRldmVtIHNlciBwZW5zYWRhcyBkZSBhY29yZG8gY29tIG8gZ3J1cG8gdGF4b27DtG1pY28uIEVzcMOpY2llcyBxdWUgZm9ybWFtIGdydXBvcyBkZXZlbSB0ZXIgYSBjb3ZhcmnDoXZlbCDigJhzaXpl4oCZLiAKCkFzIGVzdHJhdMOpZ2lhcyBkZSBlc3RyYXRpZmljYcOnw6NvIHBvZGVtIHNlciBzdWJzdGl0dcOtZGFzIHBvciBjb3ZhcmnDoXZlaXMgdGFtYsOpbSAoZXN0cmF0b3MgZXNwYWNpYWlzLyBhbm8pCgpDb21vIGNvdmFyacOhdmVsIHRlbXBvcmFsLCBwb2RlIHNlIHBlbnNhciBlbSB1c2FyLCBhbMOpbSBkbyBhbm8sIGEgZXN0YcOnw6NvIGRvIGFubyAoc2Vhc29uKSwgbyBob3LDoXJpbyBkbyBkaWEgKHBhcmEgYW5pbWFpcyBxdWUgdmFyaWFtIGEgYXRpdmlkYWRlKS4gTyBob3LDoXJpbyBkbyBkaWEgcG9kZSBzZXIgY29udmVydGlkbyBlbSB0ZW1wbyBhcMOzcyBuYXNjZXIgZG8gc29sIChjb21vIG5vIGV4ZW1wbG8pLiBNYXMgcGFyYSBpc3NvIMOpIG5lY2Vzc8OhcmlvIGNyaWFyIGVzc2EgdmFyacOhdmVsIG5vIGRhdGFzZXQuIEUgbsOjbyDDqSB0cml2aWFsIHBvcnF1ZSBwcmVjaXNhIHNhYmVyIG8gaG9yw6FyaW8gZGUgbmFzY2VyIGRvIHNvbCBlbSBjYWRhIGRpYS9sb2NhbCBwYXJhIGNhbGN1bGFyLgoKIyMjICpnZXJhciBncsOhZmljb3MgZGlzdMOibmNpYSB4IGNvdmFyacOhdmVsKgoKRXhlbXBsbyBkZSBHcsOhZmljb3MgZGUgTWFycXVlcyBldCBhbC4gMjAwNwoKIyMgKlBBUlRFIFYg4oCTIEFqdXN0YW5kbyBvcyBtb2RlbG9zKgoKRXNzZSB0cmFiYWxobyBkbyBNYXJxdWUgZXQgYWwuIDIwMDcgw6kgdW1hIGJvYSByZWZlcsOqbmNpYSBkZSBjb21vIHVzYXIgYXMgYWJvcmRhZ2VucyBDRFMgZ2xvYmFsLCBDRFMgZXN0cmF0aWZpY2FkYSBlIE1DRFMuCgpBcXVpLCDDqSBwb3Nzw612ZWwgdGVzdGFyIGFsZ3VucyBjYW1pbmhvcyBkZSBtb2RlbG9zLiBBIGVzdHJhdGlmaWNhw6fDo28gc8OzIGZheiBzZW50aWRvIHF1YW5kbyBvIHZvbHVtZSBkZSBkYWRvcyBmb3IgZ3JhbmRlLiBBaW5kYSBhc3NpbSBvIHVzbyBkZSBjb3ZhcmnDoXZlaXMgcG9kZSBzdWJzdGl0dWlyIGEgZXN0cmF0aWZpY2HDp8Ojby4gUGVuc2FyIGVtIGNvbW8gb3JpZW50YXIgbyB1c28gZGVzc2FzIGFib3JkYWdlbnMKCiMjIyAqTW9kZWxvcyBwZWxhIGFib3JkYWdlbSBDRFMg4oCTIGRhZG9zIGdsb2JhaXMqCgotIGZ1bsOnw6NvIGRzIGRvIERpc3RhbmNlIChhcmd1bWVudG9zIGLDoXNpY29zOiB0cnVuY2F0aW9uOyBrZXksIGFkanVzdG1lbnQsIHNjYWxlLi4uIGVzdHVkYXIgYXJndW1lbnRvcyBwYXJhIHZlciBzZSBtYWlzIGFsZ3VtIGludGVyZXNzYSkKCiMjIyAqTW9kZWxvcyBwZWxhIGFib3JkYWdlbSBDRFMg4oCTIGRhZG9zIGVzdHJhdGlmaWNhZG9zKgoKLSBBcXVpIHByZWNpc2EgdmVyIGRpcmVpdGluaG8gb3MgY3VpZGFkb3MgcXVlIHByZWNpc2EgdGVyIHBhcmEgYWp1c3RhciBhcyBmdW7Dp8O1ZXMgbm9zIGRhZG9zIGVzdHJhdGlmaWNhZG9zLiBBY2hvIHF1ZSBmYXogZW0gYmxvY29zLiBWYWkgYXBsaWNhbmRvIG9zIG1lc21vcyBwYXLDom1ldHJvcyBwYXJhIHRvZG9zIG9zIGVzdHJhdG9zIGEgY2FkYSBtb2RlbG8uCgotIHBhcmEgY2FkYSBlc3RyYXRvIChlc3BhY2lhbCBvdSB0ZW1wb3JhbCkgdXNhciAtIGZ1bsOnw6NvIGRzIGRvIERpc3RhbmNlIChhcmd1bWVudG9zIGLDoXNpY29zOiB0cnVuY2F0aW9uOyBrZXksIGFkanVzdG1lbnQsIHNjYWxlLi4uIGVzdHVkYXIgYXJndW1lbnRvcyBwYXJhIHZlciBzZSBtYWlzIGFsZ3VtIGludGVyZXNzYSkKCiMjIyAqTW9kZWxvcyBwZWxhIGFib3JkYWdlbSBNQ0RTIOKAkyBkYWRvcyBnbG9iYWlzKgoKQXF1aSBuw6NvIGZheiBzZW50aWRvIGVzdHJhdGlmaWNhcgoKLSBmdW7Dp8OjbyBkcyBkbyBEaXN0YW5jZSAoYXJndW1lbnRvcyBiw6FzaWNvczogdHJ1bmNhdGlvbjsga2V5LCBhZGp1c3RtZW50LCBzY2FsZS4uLiBlc3R1ZGFyIGFyZ3VtZW50b3MgcGFyYSB2ZXIgc2UgbWFpcyBhbGd1bSBpbnRlcmVzc2EuLi4gcGFyYSBhcyBjb3ZhcmnDoXZlaXMgZW50cmEgbyBhcmd1bWVudG8gZm9ybXVsYSkKCkRpY2FzIGVtIE1pbGxlciBldCBhbC4gMjAxOSBzb2JyZSBjb3ZhcmnDoXZlaXMgKHZlciBhcnF1aXZvIG5vIGRyaXZlcikuCgojIyAqUEFSVEUgVkkg4oCTIEF2YWxpYW5kbyBvcyBtb2RlbG9zKgoKIyMjICpBanVzdGUgZG9zIG1vZGVsb3MgKgoKLSBmdW7Dp8OjbyBnb2ZfZHMgCgrigJMgcGFyYSBnZXJhciBRLVEgcGxvdHMgZSB0ZXN0ZXMgYXNzb2NpYWRvcwoKIyMjICpTZWxlY2lvbmFuZG8gbW9kZWxvcyAoQUlDKSAqCgrigJMgZnVuw6fDo28gc3VtbWFyaXplX2RzX21vZGVscwoKRElDQVMgRVhUUkFTIERFIE1JTExFUiBldCBhbC4gMjAxOQoKIyMgKlBBUlRFIFZJSSDigJMgUFJPRFVUTyBGSU5BTCoKCi0gQ29tbyBvcmdhbml6YXIKCi0gSW50ZXJhdGl2aWRhZGUKCiMgQ3JpYXIgZXhwcmVzc8O1ZXMgcmVhdGl2YXMKcmVhY3RpdmUoKQpldmVudFJlYWN0aXZlKCkKCm9ic2VydmUoKQpvYnNlcnZlRXZlbnQoKQoKcmVhY3RpdmVWYWwoKQpyZWFjdGl2ZVZhbHVlcygpCgppc29sYXRlKCkKCgotIGdlcmFyIG8gdGFsIGRvY3VtZW50byBhdXRvbWF0aXphZG8gY29udGVuZG8gdG9kbyBlc3NlIGZsdXhvIG1haXMgb3MgcmVzdWx0YWRvcyBkYXMgYW7DoWxpc2VzOwoKLSB0ZW50YXIgdHJhbnNmb3JtYXIgaXNzbyBudW0gZGFzaGJvYXJkL2FwbGljYXRpdm8gw7puaWNvIGludGVncmFuZG8gY2FkYSBldGFwYSBkZXNzYSBudW1hIGRhcyBhYmFzIGRvIGRhc2hib2FyZAoKLSBQYWNvdGUgdGFyZ2V0cyBzZXJpYSDDumx0aWw/CgojIEdsb3Nzw6FyaW8KCiAtIGBFZmZvcnRgIC0gZXh0ZW5zw6NvIHRvdGFsIHBlcmNvcnJpZGEgZW0gbWV0cm9zIG5vIGNvbmp1bnRvIGRlIGRhZG9zIHNlbGVjaW9kby4KIAogLSA=